package com.piece.core.message.client.impl;

import com.piece.core.framework.enums.StatusType;
import com.piece.core.framework.exception.ServerException;
import com.piece.core.framework.support.response.AjaxResponse;
import com.piece.core.framework.util.string.JsonUtil;
import com.piece.core.framework.util.string.StringUtil;
import com.piece.core.framework.util.time.DateUtil;
import com.piece.core.log.client.LogFactory;
import com.piece.core.log.client.dto.MessageLogDTO;
import com.piece.core.log.enums.MessageLogType;
import com.piece.core.log.support.LogUtil;
import com.piece.core.message.client.SmsClient;
import com.piece.core.message.client.dto.SmsReceiveRespDTO;
import com.piece.core.message.client.dto.SmsSendRespDTO;
import com.piece.core.message.properties.SmsProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.LinkedMap;
import java.util.List;

/**
 * 短信客户端的抽象类
 */
@Slf4j
public abstract class AbstractSmsClient implements SmsClient {

    /**
     * 短信渠道配置
     */
    protected volatile SmsProperties properties;

    protected String applicationName;

    protected LogFactory auditLogFactory;

    public AbstractSmsClient(String applicationName, SmsProperties smsProperties, LogFactory auditLogFactory) {
        this.applicationName = applicationName;
        this.properties = smsProperties;
        this.auditLogFactory = auditLogFactory;
    }

    /**
     * 初始化
     */
    public final void init() {
        doInit();
    }

    /**
     * 自定义初始化
     */
    protected abstract void doInit();

    public final void refresh(SmsProperties smsProperties) {
        // 判断是否更新
        if (smsProperties.equals(this.properties)) {
            return;
        }
        this.properties = smsProperties;
        // 初始化
        this.init();
    }

    @Override
    public String getCode() {
        return this.properties.getCode();
    }

    @Override
    public final AjaxResponse sendSms(String mobile, String apiTemplateId, LinkedMap templateParams) {
        // 生成日志
        MessageLogDTO logDTO = LogUtil.buildMessageLog(applicationName);
        logDTO.setTitle(StringUtil.format("向[{}]发送短信", mobile));
        logDTO.setType(MessageLogType.SMS.getType().toString());
        logDTO.setAddress(mobile);
        logDTO.setRouter(apiTemplateId);
        logDTO.setContent(JsonUtil.mapToString(templateParams));
        logDTO = this.saveLog(logDTO);

        try {
            AjaxResponse response = doSendSms(logDTO.getLogId(), mobile, apiTemplateId, templateParams);
            SmsSendRespDTO respDTO = null;
            if (null != response.getParam()) {
                respDTO = (SmsSendRespDTO) response.getParam();
                logDTO.setContent(respDTO.getContent());
                logDTO.setEndTime(DateUtil.getDate(respDTO.getReceiveDate()));
                if (response.isSuccess()) {
                    logDTO.setStatus(StatusType.FAIL.getCode());
                }
            }
            logDTO.setDesc(response.getMsg());
            return AjaxResponse.success(response.getMsg(), respDTO);
        } catch (Throwable e) {
            logDTO.setStatus(StatusType.FAIL.getCode());
            logDTO.setDesc(e.getMessage());
            log.error("向[{}](日志编号:{})发送短信异常]", mobile, logDTO.getLogId(), e);
            return AjaxResponse.error(e.getMessage());
        } finally {
            saveLog(logDTO);
        }
    }

    protected MessageLogDTO saveLog(MessageLogDTO logDTO) {
        if (null != auditLogFactory && null != auditLogFactory.getMessageLog())
            logDTO = auditLogFactory.getMessageLog().save(logDTO);

        return logDTO;
    }

    protected abstract AjaxResponse doSendSms(String sendLogId, String mobile, String apiTemplateId, LinkedMap templateParams)
            throws Throwable;

    @Override
    public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) {
        try {
            return doParseSmsReceiveStatus(text);
        } catch (Throwable e) {
            log.error("解析短信返回结果[{}]异常]", text, e);
            throw new ServerException(e.getMessage());
        }
    }

    protected abstract List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable;

    @Override
    public AjaxResponse getSmsTemplate(String apiTemplateId) {
        try {
            return doGetSmsTemplate(apiTemplateId);
        } catch (Throwable e) {
            log.error("获得短信模板[{}] 异常", apiTemplateId, e);
            return AjaxResponse.error(e.getMessage());
        }
    }

    protected abstract AjaxResponse doGetSmsTemplate(String apiTemplateId) throws Throwable;
}
